let log4js = require('log4js');
 log4js.configure({
    appenders: {fileout: { type: "file", filename: "./logs/reward.log" },consoleout: { type: "console" }},
    categories: {default: { appenders: ["fileout","consoleout"], level: "info" }}
})
let log = log4js.getLogger("reward");
log.level = "info"; // default level is OFF - which means no logs at all.

const ethers = require("ethers");
const dayjs = require("dayjs");
const Big = require('big.js');

const db = require("./common/mysql");
const redis = require("./common/redis");
const config = require("./common/config").config;


// database
const findBuyList = () => {
    return new Promise((resolve, reject) => {
        let sql = `select * from app_buy where state=1 and reward_amount <(buy_value*${config.rewardRate}) and reward_count <${config.rewardTotal} and reward_next_time < now() order by reward_next_time asc limit 1`;
        log.debug("find buy list:",sql);
        db.query(sql, (error, results,fields) => {
            if (error) {
                reject(error);
            } else {
                resolve(results);
            }
       })
  }
)}


const saveReward=async (data)=>{
    log.info("Save reward: ",data);
    const sql = "INSERT INTO `uzi`.`app_reward` (`order_index`,`state`, `type`, `address`, `before_amount`, `change_amount`, `after_amount`, `before_count`, `change_count`, `after_count`, `change_total`, `change_delay`, `note`, `error`, `create_time`, `update_time`) VALUES "
    +`(${data.orderIndex}, 1, 'reward', '${data.address}', ${data.beforeAmount}, ${data.changeAmount},${data.afterAmount},'${data.beforeCount}', '${data.changeCount}', '${data.afterCount}', '${config.rewardTotal}', '${config.rewardDelay}', '${data.note}', '${data.error}', now(), now());`;

    db.query(sql, (error, results) => {
        if(error){
            // 创建失败
            log.error(`save reward error: ${data.orderIndex} ${error.sqlMessage} \n ${sql}`);
        } else {
            // 创建成功
            log.info(`save reward successfully ${data.orderIndex}`)
            updateBuy(data);
        }
    })
}


const updateBuy = (data) => {
    return new Promise((resolve, reject) => {
        let sql = `update app_buy set  
        reward_count=${data.afterCount},
        reward_amount=${data.afterAmount},
        reward_time=now(),
        reward_next_time=date_add(NOW(), interval ${config.rewardDelay} minute)
        where order_index=${data.orderIndex}
        `
        log.debug("update reward: ",sql);
        db.query(sql, (error, results) => {
            if (error) {
                reject(error);
            } else {
                resolve(results);
            }
        })
  }
)}

// BSC
// 私钥和钱包地址
const providerUrl = config.rpcProviderUrl;  // 替换为你的 QuickNode URL
const provider = new ethers.JsonRpcProvider(providerUrl);

const privateKey = config.walletPrivateKey;  // 替换为你的私钥
const wallet = new ethers.Wallet(privateKey, provider);

const contractAddress = config.contractAddress;
const contractABI = require("./common/abi.json");
const contract = new ethers.Contract(contractAddress, contractABI, wallet);

const bscReward=async (data) => {
    log.info("Submit bsc reward: ",data);
    try {
        const tx = await contract.reward(data.address, data.orderIndex, {
            value: ethers.parseEther(data.changeAmount) // 传入购买金额（以太币）
        });
        log.info("Transaction sent! Hash:", tx.hash);

        saveReward(data);

        // 等待交易被确认
        // const receipt = await tx.wait();
        // console.log("Transaction confirmed!", receipt);
      } catch (error) {
        console.error("Error executing transaction:", error);
      }
}


// main
const task=()=>{
    findBuyList()
       .then(buyList => {
            if(!buyList||buyList.length==0){
                log.info("no reward task found.");
                return;
            }
            log.info("find reward rows ",buyList.length);

            buyList.forEach(item => {
                const data={};
                data.address=item.buyer;
                data.orderIndex=item.order_index;

                data.beforeCount=item.reward_count;
                data.changeCount=1;
                data.afterCount=item.reward_count+1;

                data.beforeAmount=item.reward_amount;

                const totalAmount=new Big(item.buy_value).mul(config.rewardRate).toFixed(6);
                data.changeAmount=new Big(totalAmount).div(config.rewardTotal).toFixed(6);
                data.afterAmount=new Big(item.reward_amount).add(data.changeAmount).toFixed(6);

                data.note='';
                data.error='';

                // log.info(data);

                safePost(data);

                // bscReward(data);

                // saveReward(data);
                // updateBuy(data);
            });
        })
       .catch(error => {
            log.error("task error: \n",error);
        });
}


const LOCK_KEY = 'reword-lock';  // 锁的键
const LOCK_TIMEOUT = 15000;  // 锁过期时间，单位：毫秒

async function safePost(data) {
    log.info(LOCK_KEY,' lock ...');
    const lockValue = await redis.lock(LOCK_KEY, LOCK_TIMEOUT);
    if (lockValue) {
      log.info(LOCK_KEY,' lock success: ',lockValue);
      try {
        await bscReward(data);
      } finally {
        log.info(LOCK_KEY,' unlock ...');
        await redis.unlock(LOCK_KEY, lockValue);
        log.info(LOCK_KEY,' unlock success: ');
      }
    } else {
      log.info(LOCK_KEY,' lock fail',);
    }
}



const run=()=>{
    setInterval(function() {
        log.info("reward task interval");
        task();
    }, 5000);
    
}



run();

module.exports = {
	run
}





